
// ------------- GLOBAL VARS ----------------------
var map, mapOptions, startCenter, demoMapType, demoTypeOptions, infoBoxes, content;


(function ($) {
  
  /**
   * Initializes Map
   */
  function mapInit( startCenter ) {
    // Setting container for map
    var mapCanvas = $("#map_canvas")[0];
    
    // Creating an option object for the map  
    mapOptions = {
      backgroundColor: '#000000',
      center: startCenter,
      zoom: 2,
      mapTypeControlOptions: {    // Removing all usual map types from list
        mapTypeIds: ["demo"]
      },
      mapTypeControl: false,      // Hiding the map type control
      streetViewControl: false,   // Hiding the StreetView control
      
      // Positioning the controls 
      panControlOptions: {
        position: google.maps.ControlPosition.LEFT_CENTER
      },
      zoomControlOptions: {
        position: google.maps.ControlPosition.LEFT_CENTER
      }
      
    };
    
    // Initializing the map  
    map = new google.maps.Map(mapCanvas, mapOptions);
  }
  
  
    
  // --------------------- START IMAGEMAPTYPE ---------------------------------
  
  /**
   *  Initializes the ImageMapType
   */
  function mapTypeInit() {
    // Creating an option object for the ImageMapType
    demoTypeOptions = {
      getTileUrl: mapTypeGetTileUrl,
      tileSize: new google.maps.Size(256, 256),
      isPng: true,
      maxZoom: 5,     // range of
      minZoom: 1,     // zoom levels
      name: "Demo"    // label for mapTypeControl if displayed
    };
    
    // Creating the ImageMapType object
    demoMapType = new google.maps.ImageMapType(demoTypeOptions);
    // Adding "demo" to the mapTypes register
    map.mapTypes.set('demo', demoMapType);
    // Activating the "demo" MapType
    map.setMapTypeId('demo');
  }
  
  
  /**
   *  Builds url for background
   */
  function mapTypeGetTileUrl( coord, zoom ) {
    var backgroundPath = "img/bg";    // path to the background folder
    
    // Finding out if map is out of boundaries and if backgrounds should be repeated.
    // If not no background url is returned.
    var normalizedCoord = mapTypeGetNormalizedCoord(coord, zoom);
    if (!normalizedCoord) {
      return false;
    }
    
    // Calculating coordinates and return background url
    var bound = Math.pow(2, zoom);
    var xCoord = normalizedCoord.x;
    var yCoord = (bound - normalizedCoord.y - 1);
    return backgroundPath + "/" + zoom + "/" + xCoord + "/" + yCoord + ".png";
  }
  
  
  /**
   *  Normalizes the coords that tiles repeat across the x axis (horizontally)
   *  like the standard Google map tiles.
   */
  function mapTypeGetNormalizedCoord( coord, zoom ) {
    var y = coord.y;
    var x = coord.x;
  
    // tile range in one direction range is dependent on zoom level
    // 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc
    var tileRange = 1 << zoom;
    
    // don't repeat across y-axis
    if (y < 0 || y >= tileRange)
      return null;                                  
    
    // repeat across x-axis
    if (x < 0 || x >= tileRange)
      x = (x % tileRange + tileRange) % tileRange;  
  
    return { x: x, y: y };
  }
  
  // --------------------- IMAGEMAPTYPE END -----------------------------------
  
  
  
  
  // --------------------- START NAVIGATION -----------------------------------
  /**
   *  Integrates the header into Google Maps' control grid.
   *  Adds event listeners for click-event on links.
   */
  function navigationInit(){
    // Integrating the header into Google Maps' control grid
    var header = $("#header")[0];
    map.controls[google.maps.ControlPosition.TOP_CENTER].push(header);
    
    // Adding click event to links
    $("#navigation").find(" ul li a").each(function(i){
      $(this).click(function(event){
        event.preventDefault();
        
        // Getting index of the link
        var index = $("#navigation").find(" ul li a").index($(this));
        
        // Moving to startCenter if first element was clicked
        // else opening the InfoBox matching to index
        if (index == 0){
          map.panTo(startCenter);
          map.setZoom(2);
        }
        else {
          // index of content starts at 0 but in navigation chapters start at 1
          openInfoBox(index-1);
        } 
        
        // Assign active status/class to the clicked link
        navigationHighlight(index);
      });      
    });
  }
  
  /**
   * Highlights the navigation element matching
   * the visible content chapter
   */
  function navigationHighlight(index){
    var links = $("#navigation").find(" ul li a");
    // Removing all highlights
    links.removeClass("active");
    // If index is negative no element gets highlighted
    if (index >= 0)
      links.eq(index).addClass("active");
  }
  
  // ---------------------- END NAVIGATION ------------------------------------
  
  
  
  // ------------------ START CONTENT OVERLAYS --------------------------------
  
  /**
   * Creates a clickable area on the background
   * and a InfoBox for each chapter of the content
   */
  function overlaysInit(){
    for (var i = 0; i < content.length; i++){
      // Creates transparent overlay
      content[i].overlay = new google.maps.GroundOverlay(
        null, content[i].overlayBounds, { map: map });
      // Creates the InfoBox
      content[i].infoBox = infoBoxCreate(i);
    }
    
    // Closes InfoBoxes on click on map and when zoom level changes
    google.maps.event.addListener(map, 'zoom_changed', closeInfoBoxes); 
    google.maps.event.addListener(map, 'click', closeInfoBoxes);
  }
  
  /**
   * Creates InfoBox
   */
  function infoBoxCreate( index ){
    // Loading the matching chapter & position from the content object
    var myOptions = {
         content: content[index].container[0]
        ,position: content[index].position
        ,alignBottom: true
        ,pixelOffset: new google.maps.Size(-300, 0)
        ,infoBoxClearance: new google.maps.Size(50, 110)
        ,closeBoxMargin: "19px 5px 0"
        ,closeBoxURL: "img/close.png"
        ,maxWidth: 0
    };
    var infoBox = new InfoBox(myOptions);
    
    // Handling clicks on overlays
    google.maps.event.addListener(content[index].overlay, 'click', function(event){
      openInfoBox(index);
      navigationHighlight(index+1);
    });
    // Handling clicks on close button
    google.maps.event.addListener(infoBox, 'closeclick', function(event){
      navigationHighlight(-1); // Deactivate navigation element
    });

    return infoBox;
  }
  
  /**
   * Open a specific InfoBox
   */
  function openInfoBox( index ){
    // Closing all InfoBoxes
    for (var i = 0; i < content.length; i++){
      content[i].infoBox.close();    
    }
    // Opening the InfoBox
    if (index >= 0){
      map.setZoom(4);
      // Delay the opening because zoom and panTo at the same time can cause problems
      setTimeout(function(){ content[index].infoBox.open(map) }, 250);
    }
  }
  
  /**
   * Closes InfoBoxes and deactivates navigation elements
   */
  function closeInfoBoxes(){
      navigationHighlight(-1);
      openInfoBox(-1);
  }
  
  /**
   * Adds a tab function to the content sections
   * of each InfoBox
   */
  function contentTabs(){
    // Applying to all .content elements
    $("#content .content").each(function(i){
      var thisContent   = $(this);
      var headlineLinks = $(this).find(" .headlines a");
      var sections      = $(this).find(" .section");
      
      sections.hide();
      
      // Adding click event to all links in .headlines
      headlineLinks.each(function(a){
        $(this).click(function(event){
          event.preventDefault();
          
          // Managing active navigation element
          headlineLinks.removeClass("active");
          $(this).addClass("active");
          
          // Managing visible content element
          sections.hide();
          var index = headlineLinks.index($(this));
          sections.eq(index).slideDown('fast');
        })
        headlineLinks.first().click();
      })
    });
  }
  
  // ------------------- END CONTENT OVERLAYS ---------------------------------
  
  
    
  function debug( object ){
    map.setOptions({
      draggableCursor: "crosshair",
      draggingCursor: "crosshair"
    });    
    $("#debug").show();
    var debug = $("#debug")[0];
    map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(debug);
    
    
    google.maps.event.addListener(map, 'click', function(event) {
      $("#debug .mouse").html("mouse LatLng" + fromContainerPixelToLatLng(new google.maps.Point()));
    });
    
    if (object.length() != 0){
      var bigStep = 0.1;
      var smallStep = 0.005;
      
      var x = {"nn":bigStep, "n":smallStep, "s":-smallStep, "ss": -bigStep, "ee":0, "e":0, "w":0, "ww":0};
      var y = {"ee":bigStep, "e":smallStep, "w":-smallStep, "ww": -bigStep, "nn":0, "n":0, "s":0, "ss":0};
      
      $("#debug").find(" a").live("click",function(e){
        e.preventDefault();
        var oldPosition = object.getPosition();
        var direction = $(this).attr("class");
        
        object.setPosition(new google.maps.LatLng(oldPosition.lat() + x[direction], oldPosition.lng() + y[direction]));
        $("#debug .coordinates").html("" + object.getPosition());
      });
    }
  }
  
  
  
  $(document).ready(function() { 
    content = [
      {
        container: $("#content-1"),
        position: new google.maps.LatLng(-75.92692542233661, -117.05898437499941),
        overlayBounds: new google.maps.LatLngBounds(
          new google.maps.LatLng(-77.96971812882364, -126.14257812499999),
          new google.maps.LatLng(-73.55190672379996, -107.99316406249999))
      },
      {
        container: $("#content-2"),
        position: new google.maps.LatLng(-54.34816974738091, -38.535898437500016),
        overlayBounds: new google.maps.LatLngBounds(
          new google.maps.LatLng(-59.28581538198265, -47.65624999999999),
          new google.maps.LatLng(-48.71671069623162, -29.506835937499993))
      },
      {
        container: $("#content-3"),
        position: new google.maps.LatLng(-78.33456857361996, 19.09718750000001),
        overlayBounds: new google.maps.LatLngBounds(
          new google.maps.LatLng(-80.03440964867912, 10.000000000000004),
          new google.maps.LatLng(-76.34035987663286, 28.193359375000004))
      },
      {
        container: $("#content-4"),
        position: new google.maps.LatLng(-47.67667120749752, 77.13097656249936),
        overlayBounds: new google.maps.LatLngBounds(
          new google.maps.LatLng(-53.40659491560606, 68.095703125),
          new google.maps.LatLng(-41.2080150548096, 86.201171875))
      },
      {
        container: $("#content-5"),
        position: new google.maps.LatLng(-76.47491003626945, 125.9965624999991),
        overlayBounds: new google.maps.LatLngBounds(
          new google.maps.LatLng(-78.43683501498795, 116.875),
          new google.maps.LatLng(-74.18670914402327, 135.068359375))
      }
    ];
    contentTabs();
    
    // coordinates for center of the map (more or less)
    startCenter = new google.maps.LatLng(-60.86391376572419, -18.652343749999996);  
    mapInit(startCenter);
    mapTypeInit();
    navigationInit();
    overlaysInit(); 
    
    //debug();
  });  
  
})(jQuery);